// use std::rc::Rc;
use std::sync::{Arc, mpsc, Mutex};
use std::thread;
use std::time::Duration;

fn main() {
    example_13();
}

#[allow(dead_code)]
fn example_06(){
    let (sdr, rcr) = mpsc::channel();
    thread::spawn(move||{
        let val = String::from("Hi");
        sdr.send(val).unwrap();
        // println!("val is {}", val);
    });

    let received = rcr.recv().unwrap();
    println!("Got message: {}", received);
}

#[allow(dead_code)]
fn example_10(){
    let (sdr, rcr) = mpsc::channel();
    thread::spawn(move||{
        let mut vals = vec![];
        vals.push(String::from("Hi"));
        vals.push(String::from("from"));
        vals.push(String::from("the"));
        vals.push(String::from("thread"));

        for v in vals{
            sdr.send(v).unwrap();
            thread::sleep(Duration::from_secs(2));
        }

    });

    for item in rcr{
        println!("Got:{}", item);
    }

}

#[allow(dead_code)]
fn example_11(){
    let (sender, rcr) = mpsc::channel();

    let senderbk = mpsc::Sender::clone(&sender);    // clone one producer
    thread::spawn(move||{
        let mut vals = vec![];
        vals.push(String::from("1:A"));
        vals.push(String::from("1:B"));
        vals.push(String::from("1:C"));
        vals.push(String::from("1:D"));

        for v in vals{
            sender.send(v).unwrap();
            thread::sleep(Duration::from_secs(2));
        }

    });

    thread::spawn(move||{
        let mut vals = vec![];
        vals.push(String::from("2:E"));
        vals.push(String::from("2:F"));
        vals.push(String::from("2:G"));
        vals.push(String::from("2:H"));

        for v in vals{
            senderbk.send(v).unwrap();
            thread::sleep(Duration::from_secs(2));
        }
    });


    for item in rcr{
        println!("Got:{}", item);
    }
}

#[allow(dead_code)]
fn example_12(){
    let m = Mutex::new(5);
    {
        let mut num = m.lock().unwrap();
        *num = 6;
    }

    println!("m = {:?}", m);
}

#[allow(dead_code)]
fn example_13(){
    // let counter = Mutex::new(0); // can't be moved into closure
    // let counter = Rc::new(Mutex::new(0));// can't be sent between threads safely
    let counter = Arc::new(Mutex::new(0));
    let mut handlers = vec![];

    for _ in 0..10{
        let counter = Arc::clone(&counter);
        let handler = thread::spawn(move||{
            let mut num = counter.lock().unwrap(); //Due to not implementing the `Copy` trait
            *num += 1;
        });
        handlers.push(handler);
    }

    for handler in handlers{
        handler.join().unwrap();
    }
    println!("Result is : {}", *counter.lock().unwrap());
}